﻿using Action = Styx.TreeSharp.Action;
using Styx;
using Styx.Common;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Kitty
{
    public partial class Main : CombatRoutine
    {
        internal readonly Version Version = new Version(1, 0, 0);
        public override string Name { get { return "Pasterke's Feral Combat Routine"; } }
        public override WoWClass Class { get { return WoWClass.Druid; } }
        public LocalPlayer Me { get { return StyxWoW.Me; } }

        private Composite _preCombatBuffs, _combatBuffs, _Heal, _Combat, _Pull, _pullBuffs;
        public override Composite PreCombatBuffBehavior { get { using (StyxWoW.Memory.AcquireFrame()) return _preCombatBuffs; } }
        public override Composite CombatBuffBehavior { get { using (StyxWoW.Memory.AcquireFrame()) return _combatBuffs; } }
        public override Composite HealBehavior { get { using (StyxWoW.Memory.AcquireFrame()) return _Heal; } }
        public override Composite CombatBehavior { get { using (StyxWoW.Memory.AcquireFrame()) return _Combat; } }
        public override Composite PullBehavior { get { using (StyxWoW.Memory.AcquireFrame()) return _Pull; } }
        public override Composite PullBuffBehavior { get { using (StyxWoW.Memory.AcquireFrame()) return _pullBuffs; } }

        public override bool WantButton { get { return true; } }

        public override void OnButtonPress()
        {
            Form2 ConfigForm = new Form2(CRSettings.myPrefs, CRSettings.myPrefs.SavePath);
            ConfigForm.ShowDialog();
        }
        
        #region Initialize
        public override void Initialize()
        {
            _preCombatBuffs = createBuffs();
            _combatBuffs = createBuffs();
            _Heal = createBuffs();
            _Combat = createCombat();
            _Pull = createPull();
            _pullBuffs = createPullBuffs();
            Lua.Events.AttachEvent("MODIFIER_STATE_CHANGED", HandleModifierStateChanged);
        }
        #endregion

        #region rest
        public override bool NeedRest
        {
            get
            {
                if (SpellManager.HasSpell("Healing Touch")
                    && Me.HealthPercent <= CRSettings.myPrefs.HealingTouchOoc)
                {
                    return true;
                }
                if (SpellManager.HasSpell("Rejuvenation")
                    && Me.HealthPercent <= CRSettings.myPrefs.RejuOoc
                    && Me.HealthPercent > CRSettings.myPrefs.HealingTouchOoc)
                {
                    return true;
                }
                return false;
            }
        }

        public override void Rest()
        {
            if (SpellManager.HasSpell("Rejuvenation")
                && !Me.Mounted
                && !Me.IsFlying
                && healthpercentBetween(CRSettings.myPrefs.RejuOoc, CRSettings.myPrefs.food)
                && !Me.IsDead
                && !Me.IsGhost
                && !buffExists("Rejuvenation", Me))
            {
                SpellManager.Cast("Rejuvenation", Me);
            }
            if (SpellManager.HasSpell("Healing Touch")
                && !Me.IsFlying
                && !Me.Mounted
                && healthpercentBetween(CRSettings.myPrefs.HealingTouchOoc, CRSettings.myPrefs.food)
                && !Me.IsDead
                && !Me.IsGhost)
            {
                SpellManager.Cast("Healing Touch", Me);
            }
            if (Me.HealthPercent <= CRSettings.myPrefs.food
                && !Me.IsDead
                && !Me.IsGhost
                && !Me.IsSwimming
                && !Me.Mounted
                && !Me.IsFlying)
            {
                Styx.CommonBot.Rest.Feed();
            }
        }

        #endregion rest

        #region Pull buffs
        Composite createPullBuffs()
        {
            return new PrioritySelector(
                new Decorator(ret => Paused, crPaused()),
                Cast("Cat Form", "Cat Form", 2, ret => gotTarget
                    && Me.Shapeshift != ShapeshiftForm.Cat
                    && Me.Shapeshift != ShapeshiftForm.Aqua),
                Cast("Prowl", "Prowl", 2, ret => gotTarget
                    && CRSettings.myPrefs.pounce
                    && Me.Shapeshift == ShapeshiftForm.Cat
                    && !spellOnCooldown("Prowl")
                    && !buffExists("Prowl", Me))
             );
        }
        #endregion pull buffs

        #region Pull
        Composite createPull()
        {
            return new PrioritySelector(
                new Decorator(ret => Paused, crPaused()),

                new Decorator(ret => gotTarget && SpellManager.HasSpell("Pounce") && CRSettings.myPrefs.pounce && Me.CurrentTarget.Distance > 4, moveControlls(4)),
                new Decorator(ret => gotTarget && SpellManager.HasSpell("Pounce") && CRSettings.myPrefs.pounce && buffExists("Prowl", Me), pullPounce()),

                new Decorator(ret => gotTarget && SpellManager.HasSpell("Wild Charge") && CRSettings.myPrefs.wildCharge && Me.CurrentTarget.Distance > 25, moveControlls(24)),
                new Decorator(ret => gotTarget && SpellManager.HasSpell("Wild Charge") && !spellOnCooldown("Wild Charge") && CRSettings.myPrefs.wildCharge, pullWildCharge()),

                new Decorator(ret => gotTarget && Me.CurrentTarget.Distance > 35, moveControlls(35)),
                new Decorator(ret => gotTarget && LastSpell != "Faerie Fire" && LastSpell != "Faerie Swarm", pullFaerieFire()),

                new Decorator(ret => gotTarget && !SpellManager.HasSpell("Cat Form") && Me.CurrentTarget.Distance > 35, moveControlls(35)),
                new Decorator(ret => gotTarget && !SpellManager.HasSpell("Cat Form"),
                    pullMoonfireWrath()),

                new Decorator(ret => gotTarget 
                    && SpellManager.HasSpell("Rake")
                    && Me.CurrentTarget.Distance > 4,
                    moveControlls(3.5f)),
                new Decorator(ret => gotTarget, pullRake())

            );
        }
        #endregion

        #region Combat
        Composite createCombat()
        {
            return new PrioritySelector(
                new Decorator(ret => Paused, crPaused()),
                new Decorator(ret => gotTarget && !SpellManager.HasSpell("Cat Form") && Me.CurrentTarget.Distance > 35, moveControlls(35)),
                new Decorator(ret => gotTarget && !SpellManager.HasSpell("Cat Form"), LowieRotation()),

                new Decorator(ret => gotTarget && !checkRange(3.5f), moveControlls(3.5f)),
                new Decorator(ret => gotTarget && CRSettings.myPrefs.Facing && !Me.IsSafelyFacing(Me.CurrentTarget), targetFacing()),
                new Decorator(ret => Me.Specialization == WoWSpec.DruidFeral
                    && (SwitchBearForm || buffExists("Might of Ursoc", Me) || (addCount >= CRSettings.myPrefs.SwitchBear && !Me.GroupInfo.IsInRaid && !Me.IsInInstance))
                    && !PauseAoe,
                    BearRotation()),
                new Decorator(ret => gotTarget
                    && Me.Specialization == WoWSpec.DruidFeral
                    && !SwitchBearForm
                    && !buffExists("Might of Ursoc", Me), CatRotation())
                );
        }
        Composite CatRotation()
        {
            return new PrioritySelector(
                //new Decorator(ret => gotTarget && addCount >= CRSettings.myPrefs.StartCatAoe, AoeRotation()),
                Cast("Cat Form", "Cat Form", 3, ret => gotTarget
                    && Me.Shapeshift != ShapeshiftForm.Cat),
                    autoAttack(),
                Cast("Wild Charge", "Wild Charge", 3, ret => gotTarget
                    && SpellManager.HasSpell("Wild Charge")
                    && !spellOnCooldown("Wild Charge")
                    && targetDistanceBetween(8, 25)),
                new Decorator(ret => gotTarget
                    && SpellManager.HasSpell("Healing Touch")
                    && CRSettings.myPrefs.predatoryHeal
                    && buffExists("Predatory Swiftness", Me)
                    && buffTimeLeft("Predatory Swiftness", Me) >= 1800
                    && LastSpell != "Healing Touch",
                    useHealingTouchOnOthers()),
                Cast("Healing Touch", "Healing Touch", 3, ret => gotTarget
                    && SpellManager.HasSpell("Healing Touch")
                    && !CRSettings.myPrefs.predatoryHeal
                    && buffExists("Predatory Swiftness", Me)
                    && buffTimeLeft("Predatory Swiftness", Me) >= 1800
                    && LastSpell != "Healing Touch"),
                Cast("Skull Bash", "Skull Bash", 3, ret => gotTarget
                    && SpellManager.HasSpell("Skull Bash")
                    && CRSettings.myPrefs.interrupt
                    && !spellOnCooldown("Skull Bash")
                    && (Me.CurrentTarget.IsCasting  && Me.CanInterruptCurrentSpellCast)
                    && LastSpell != "Mighty Bash"),
                Cast("Mighty Bash", "Mighty Bash", 3, ret => gotTarget
                    && SpellManager.HasSpell("Mighty Bash")
                    && CRSettings.myPrefs.interrupt
                    && !spellOnCooldown("Mighty Bash")
                    && (Me.CurrentTarget.IsCasting && Me.CanInterruptCurrentSpellCast)
                    && LastSpell != "Skull Bash"),
                Cast("Tiger's Fury", "Tiger's Fury", 3, ret => gotTarget
                    && SpellManager.HasSpell("Tiger's Fury")
                    && !buffExists("Berserk", Me)
                    && !buffExists("Lifeblood", Me)
                    && !buffExists("Bloodlust", Me)
                    && !buffExists("Heroism", Me)
                    && !buffExists("Time Warp", Me)
                    && !buffExists("Ancient Hysteria", Me)
                    && !buffExists("Drums of Rage", Me)
                    && Me.EnergyPercent <= 30
                    && LastSpell != "Tiger's Fury"
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast("Thrash", "Thrash", 5, ret => gotTarget
                    && SpellManager.HasSpell("Thrash")
                    && !debuffExists("Thrash", Me.CurrentTarget)
                    && addCount >= CRSettings.myPrefs.StartCatAoe
                    && LastSpell != "Thrash"
                    && (Me.EnergyPercent >= 50 || buffExists("Clearcasting", Me))
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast("Swipe", "Swipe", 5, ret => gotTarget
                    && SpellManager.HasSpell("Swipe")
                    && addCount >= CRSettings.myPrefs.StartCatAoe
                    && Me.EnergyPercent >= 45
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast(FEROCIOUSBITE, "Ferocious Bite", 3, ret => gotTarget
                    && SpellManager.HasSpell("Ferocious Bite")
                    && ((SpellManager.HasSpell(RIP) && debuffExists(RIP, Me.CurrentTarget) && debuffTimeLeft(RIP, Me.CurrentTarget) >= 3000
                    && Me.ComboPoints >= 5 && Me.EnergyPercent >= 25 && Me.CurrentTarget.IsWithinMeleeRange)
                    || (!IsWoWBoss(Me.CurrentTarget) && Me.ComboPoints >= 3 && Me.EnergyPercent >= 25 && Me.CurrentTarget.IsWithinMeleeRange)
                    || (!SpellManager.HasSpell(RIP) && Me.ComboPoints >= 3 && Me.EnergyPercent >= 25 && Me.CurrentTarget.IsWithinMeleeRange))
                    && addCount < CRSettings.myPrefs.StartCatAoe),
                Cast("Savage Roar", "Savage Roar", 3, ret => gotTarget
                    && SpellManager.HasSpell("Savage Roar")
                    && ((Me.ComboPoints == 0 && CRSettings.myPrefs.SavageryGlyph && !buffExists("Savage Roar", Me) && Me.EnergyPercent >= 25)
                    || Me.ComboPoints > 0 && !buffExists("Savage Roar", Me) && Me.EnergyPercent >= 25)
                    && useSavageRoar
                    && LastSpell != "Savage Roar"),
                Cast("Thrash", "Thrash", 3, ret => gotTarget
                    && SpellManager.HasSpell("Thrash")
                    && !debuffExists("Thrash", Me.CurrentTarget)
                    && buffExists("Clearcasting", Me)
                    && LastSpell != "Thrash"),
                Cast(RAKE, "Rake", 3, ret => gotTarget
                    && SpellManager.HasSpell("Rake")
                    && !debuffExists(RAKE, Me.CurrentTarget)
                    && Me.EnergyPercent >= 35
                    && targetExistence(Me.CurrentTarget) >= 15
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast(RIP, "Rip", 3, ret => gotTarget
                    && SpellManager.HasSpell("Rip")
                    && !debuffExists(RIP, Me.CurrentTarget)
                    && Me.EnergyPercent >= 30
                    && Me.ComboPoints >= 5
                    && IsWoWBoss(Me.CurrentTarget)
                    && Me.CurrentTarget.IsWithinMeleeRange
                    && addCount <= CRSettings.myPrefs.StartCatAoe),
                Cast("Faerie Fire", "Faerie Fire", 3, ret => gotTarget
                    && addCount < CRSettings.myPrefs.StartCatAoe
                    && SpellManager.HasSpell("Faerie Fire")
                    && !SpellManager.HasSpell("Faerie Swarm")
                    && !debuffExists(WEAKENEDARMOR, Me.CurrentTarget)
                    && !spellOnCooldown("Faerie Fire")),
                Cast("Faerie Swarm", "Faerie Swarm", 3, ret => gotTarget
                    && addCount < CRSettings.myPrefs.StartCatAoe
                    && SpellManager.HasSpell("Faerie Swarm")
                    && !debuffExists(WEAKENEDARMOR, Me.CurrentTarget)
                    && !spellOnCooldown("Faerie Swarm")
                    && addCount < CRSettings.myPrefs.StartCatAoe),
                Cast("Berserk", "Berserk", 3, ret => gotTarget
                    && SpellManager.HasSpell("Berserk")
                    && !spellOnCooldown("Berserk")
                    && ((CRSettings.myPrefs.useBerserk == CRSettings.CooldownPrefs.OnCoolDown && targetExistence(Me.CurrentTarget) >= 15)
                    || (CRSettings.myPrefs.useBerserk == CRSettings.CooldownPrefs.Bosses && IsWoWBoss(Me.CurrentTarget)))
                    && Me.CurrentTarget.IsWithinMeleeRange),
                new Decorator(ret => (CRSettings.myPrefs.trinket1 == CRSettings.CooldownPrefs.OnCoolDown 
                    || (CRSettings.myPrefs.trinket1 == CRSettings.CooldownPrefs.Bosses && IsWoWBoss(Me.CurrentTarget))),
                    useTrinket1()),
                new Decorator(ret => (CRSettings.myPrefs.trinket2 == CRSettings.CooldownPrefs.OnCoolDown
                    || (CRSettings.myPrefs.trinket2 == CRSettings.CooldownPrefs.Bosses && IsWoWBoss(Me.CurrentTarget))),
                    useTrinket2()),
                new Decorator(ret => (CRSettings.myPrefs.gloves == CRSettings.CooldownPrefs.OnCoolDown
                    || (CRSettings.myPrefs.gloves == CRSettings.CooldownPrefs.Bosses && IsWoWBoss(Me.CurrentTarget))),
                    useEngiGloves()),
                new Decorator(ret => ((CRSettings.myPrefs.virmenpotion == CRSettings.PotionsPrefs.Bosses_All && IsWoWBoss(Me.CurrentTarget))
                    || (CRSettings.myPrefs.virmenpotion == CRSettings.PotionsPrefs.Bosses_Raid_Only && IsWoWBoss(Me.CurrentTarget) && Me.GroupInfo.IsInRaid))
                    && buffExists("Berserk", Me),
                    useVirmenPotion()),
                Cast("Incarnation", "Incarnation", 3, ret => gotTarget
                    && SpellManager.HasSpell("Incarnation")
                    && !spellOnCooldown("Incarnation")
                    && ((CRSettings.myPrefs.useIncarnation == CRSettings.CooldownPrefs.OnCoolDown && targetExistence(Me.CurrentTarget) >= 30)
                    || (CRSettings.myPrefs.useIncarnation == CRSettings.CooldownPrefs.Bosses && IsWoWBoss(Me.CurrentTarget)))
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast("Ravage", "Ravage", 3, ret => gotTarget
                    && SpellManager.HasSpell("Ravage")
                    && buffExists("Incarnation: King of the Jungle", Me)
                    && Me.EnergyPercent >= 45
                    && Me.CurrentTarget.IsWithinMeleeRange
                    && addCount < CRSettings.myPrefs.StartCatAoe),
                Cast("Shred", "Shred", 3, ret => gotTarget
                    && SpellManager.HasSpell("Shred")
                    && CRSettings.myPrefs.shred
                    && ((Me.IsSafelyBehind(Me.CurrentTarget) && Me.EnergyPercent >= 40)
                    || (CRSettings.myPrefs.ShredGlyph && (buffExists("Tiger's Fury", Me) || buffExists("Berserk", Me) && Me.EnergyPercent >= 40)))
                    && (debuffExists("Rake", Me.CurrentTarget) || debuffExists("Thrash", Me.CurrentTarget))
                    && Me.CurrentTarget.IsWithinMeleeRange
                    && addCount < CRSettings.myPrefs.StartCatAoe),
                Cast("Lifeblood", "Lifeblood", 3, ret => gotTarget
                    && SpellManager.HasSpell("Lifeblood")
                    && !spellOnCooldown("Lifeblood")
                    && !buffExists("Tiger's Fury", Me)
                    && !buffExists("Bloodlust", Me)
                    && !buffExists("Heroism", Me)
                    && !buffExists("Time Warp", Me)
                    && !buffExists("Ancient Hysteria", Me)
                    && !buffExists("Drums of Rage", Me)
                    && ((CRSettings.myPrefs.lifeblood == CRSettings.CooldownPrefs.OnCoolDown && Me.EnergyPercent <= 25)
                    || (CRSettings.myPrefs.lifeblood == CRSettings.CooldownPrefs.Bosses && IsWoWBoss(Me.CurrentTarget) && Me.EnergyPercent <= 25))
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast(MANGLE, "Mangle", 3, ret => gotTarget
                    && SpellManager.HasSpell("Mangle")
                    && Me.EnergyPercent >= 35
                    && Me.CurrentTarget.IsWithinMeleeRange
                    && addCount < CRSettings.myPrefs.StartCatAoe)
                );
        }

        Composite AoeRotation()
        {
            return new PrioritySelector(
                Cast("Cat Form", "Cat Form",2, ret => gotTarget
                    && Me.Shapeshift != ShapeshiftForm.Cat),
                autoAttack(),
                new Decorator(ret => gotTarget
                    && SpellManager.HasSpell("Healing Touch")
                    && CRSettings.myPrefs.predatoryHeal
                    && buffExists("Predatory Swiftness", Me)
                    && buffTimeLeft("Predatory Swiftness", Me) >= 1800
                    && LastSpell != "Healing Touch",
                    useHealingTouchOnOthers()),
                Cast("Healing Touch", "Healing Touch",5, ret => gotTarget
                    && SpellManager.HasSpell("Healing Touch")
                    && !CRSettings.myPrefs.predatoryHeal
                    && buffExists("Predatory Swiftness", Me)
                    && buffTimeLeft("Predatory Swiftness", Me) >= 1800
                    && LastSpell != "Healing Touch"),
                Cast("Tiger's Fury", "Tiger's Fury",5, ret => gotTarget
                    && SpellManager.HasSpell("Tiger's Fury")
                    && !buffExists("Berserk", Me)
                    && !buffExists("Lifeblood", Me)
                    && !buffExists("Bloodlust", Me)
                    && !buffExists("Heroism", Me)
                    && !buffExists("Time Warp", Me)
                    && !buffExists("Ancient Hysteria", Me)
                    && !buffExists("Drums of Rage", Me)
                    && Me.EnergyPercent <= 30
                    && LastSpell != "Tiger's Fury"
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast("Savage Roar", "Savage Roar",5, ret => gotTarget
                    && SpellManager.HasSpell("Savage Roar")
                    && ((Me.ComboPoints == 0 && CRSettings.myPrefs.SavageryGlyph && !buffExists("Savage Roar", Me) && Me.EnergyPercent >= 25)
                    || Me.ComboPoints > 0 && !buffExists("Savage Roar", Me) && Me.EnergyPercent >= 25)
                    && useSavageRoar
                    && LastSpell != "Savage Roar"),
                Cast("Thrash", "Thrash",5, ret => gotTarget
                    && SpellManager.HasSpell("Thrash")
                    && !debuffExists("Thrash", Me.CurrentTarget)
                    && (buffExists("Clearcasting", Me) || Me.EnergyPercent >= 50)
                    && LastSpell != "Thrash"
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast("Swipe", "Swipe",5, ret => gotTarget
                    && SpellManager.HasSpell("Swipe")
                    && Me.EnergyPercent >= 45
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast("Lifeblood", "Lifeblood",5, ret => gotTarget
                    && SpellManager.HasSpell("Lifeblood")
                    && !spellOnCooldown("Lifeblood")
                    && !buffExists("Tiger's Fury", Me)
                    && !buffExists("Bloodlust", Me)
                    && !buffExists("Heroism", Me)
                    && !buffExists("Time Warp", Me)
                    && !buffExists("Ancient Hysteria", Me)
                    && !buffExists("Drums of Rage", Me)
                    && Me.EnergyPercent <= 25
                    && Me.CurrentTarget.IsWithinMeleeRange)
                );
        }
        Composite BearRotation()
        {
            return new PrioritySelector(
                Cast("Bear Form", "Bear Form",4, ret => gotTarget
                    && Me.Shapeshift != ShapeshiftForm.Bear),
                    autoAttack(),
                Cast("Maul", "Maul",4, ret => gotTarget
                    && SpellManager.HasSpell("Maul")
                    && Me.RagePercent >= 35),
                Cast("Mangle", "Mangle",4, ret => gotTarget
                    && SpellManager.HasSpell("Mangle")
                    && !spellOnCooldown("Mangle")
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast("Thrash", "Thrash",4, ret => gotTarget
                    && SpellManager.HasSpell("Thrash")
                    && !debuffExists("Thrash", Me.CurrentTarget)
                    && !spellOnCooldown("Thrash")
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast("Swipe", "Swipe",4, ret => gotTarget
                    && SpellManager.HasSpell("Swipe")
                    && !PauseAoe
                    && addCount > 1
                    && Me.RagePercent >= 15
                    && Me.CurrentTarget.IsWithinMeleeRange),
                Cast("Lacerate", "Lacerate",4, ret => gotTarget
                    && SpellManager.HasSpell("Lacerate")
                    && Me.CurrentTarget.IsWithinMeleeRange)

                );
        }
        Composite LowieRotation()
        {
            return new PrioritySelector(
                new Decorator(ret => gotTarget && !checkRange(35), moveControlls(35)),
                Cast("Moonfire", "Moonfire", 1, ret => gotTarget
                    && SpellManager.HasSpell("Moonfire")
                    && !debuffExists("Moonfire", Me.CurrentTarget)),
                Cast("Wrath", "Wrath", 1, ret => gotTarget
                    && SpellManager.HasSpell("Wrath"))

                );
        }
        Composite GuardianRotation()
        {
            return new PrioritySelector(

                );
        }
        #endregion


        private Composite autoAttack()
        {
            return new PrioritySelector(
                    new Decorator(ret => !StyxWoW.Me.IsAutoAttacking && Me.CurrentTarget.IsWithinMeleeRange,
                        new Action(ret =>
                        {
                            Lua.DoString("StartAttack()");
                            return RunStatus.Failure;
                        }))
                    );
        }

        Composite crPaused()
        {
            return new Action(ret =>
            {
                return;
            });
        }
    }
}
